package com.raidpoints.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import org.cobogw.gwt.user.client.ui.VerticalTabBar;

import com.bradrydzewski.gwt.calendar.client.Appointment;
import com.bradrydzewski.gwt.calendar.client.AppointmentStyle;
import com.bradrydzewski.gwt.calendar.client.Calendar;
import com.bradrydzewski.gwt.calendar.client.CalendarSettings;
import com.bradrydzewski.gwt.calendar.client.CalendarSettings.Click;
import com.bradrydzewski.gwt.calendar.client.CalendarViews;
import com.bradrydzewski.gwt.calendar.client.event.DateRequestEvent;
import com.bradrydzewski.gwt.calendar.client.event.DateRequestHandler;
import com.bradrydzewski.gwt.calendar.client.event.TimeBlockClickEvent;
import com.bradrydzewski.gwt.calendar.client.event.TimeBlockClickHandler;
import com.bradrydzewski.gwt.calendar.client.monthview.MonthView;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SourcesTabEvents;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TabListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DatePicker;
import com.raidpoints.client.RaidPoints.AuthType;

public class RaidCalendar extends Composite implements RaidPoints.HasRedraw{
	VerticalPanel vpan;
	RaidPoints rp;
	Calendar cal;
	CalendarSettings cset;
	DatePicker dpick;
	HashMap<Appointment,event> idmap;
	DockLayoutPanel dpan;
	boolean doit;
	boolean prevmil;
	HTML legend, adminin, msignlabel;
	Button listButton;
	ScrollPanel span;
	ListBox msignBox;
	Button signButton;
	ArrayList<event> msignlist;
	MyMonth mymonth;
	CheckBox calheight;
	VerticalTabBar tabbar;
	String cgames, cgroups;
	boolean craids, cue;
	Button editTab;
	MSignupPopup spop;

	RaidCalendar(RaidPoints mrp){
		rp = mrp;
		vpan = new VerticalPanel();
		dpan = new DockLayoutPanel(Unit.EM);
		span = new ScrollPanel();
		span.setStyleName("calspan");
		cgames = "";
		cgroups = "";
		spop = null;
		msignlist = new ArrayList<event>();
		initWidget(span);
		span.setSize("100%","100%");
		span.add(vpan);
		craids = true; cue = true;
		prevmil = rp.mil;
		idmap = new HashMap<Appointment,event>();
		mymonth = new MyMonth(rp);
		tabbar = new VerticalTabBar();
		cal = new Calendar(mymonth);

		legend = new HTML("<table width=\"20\" height=\"20\"><tr><td bgcolor=\"8997A5\"></td></tr></table>Not signed up<table width=\"20\" height=\"20\"><tr><td bgcolor=\"668CD9\"></td></tr></table>Signed up" +
				"<table width=\"20\" height=\"20\"><tr><td bgcolor=\"4CB052\"></td></tr></table>Slotted<table width=\"20\" height=\"20\"><tr><td bgcolor=\"A992A9\"></td></tr></table>Standby<br><br>Click raid to view points, double click to sign up<br>Ctrl-click to select multiple raids");
		adminin = new HTML("Double click day to add event");
		adminin.setVisible(false);
		listButton = new Button("Switch to List View");
		listButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				rp.CalSwitch(false);
			}
		});

		calheight = new CheckBox("Extend Cal Height");
		calheight.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
			@Override
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				if(event.getValue()) rp.calheight = 1;
				else rp.calheight = 0;
				ChangeHeight();
				Redraw();
				rp.rpsvc.SetCalHeight(rp.calheight, rp.stringCallback);
			}
		});

		CalendarSettings cset = new CalendarSettings();
		cset.setPixelsPerInterval(10);
		cset.setEnableDragDrop(false);
		cset.setScrollToHour(12);
		cset.setTimeBlockClickNumber(Click.Double);
		cal.setSettings(cset);
		cal.setDate(new Date());
		cal.setDays(6);
		//cal.setView(CalendarViews.MONTH);


		cal.addTimeBlockClickHandler(new TimeBlockClickHandler<Date>(){
			@Override
			public void onTimeBlockClick(TimeBlockClickEvent<Date> event) {
				if(rp.auth == AuthType.admin || rp.auth == AuthType.cl){
					if(rp.ctrldown){
						NewEventBoxOther neb = new NewEventBoxOther(rp,event.getTarget(),null);
						neb.center(); neb.show();
					}	
					else{
						NewEventBox neb  = new NewEventBox(rp,event.getTarget(),null);
						neb.center(); neb.show();
					}
				}
				else if(rp.auth == AuthType.user){
					NewEventBoxOther neb = new NewEventBoxOther(rp,event.getTarget(),null);
					neb.center(); neb.show();
				}
			}
		});



		cal.addSelectionHandler(new SelectionHandler<Appointment>(){
			@Override
			public void onSelection(final SelectionEvent<Appointment> event) {
				if(event.getSelectedItem() == null) return;
				if(rp.ctrldown){
					event ae = idmap.get(event.getSelectedItem());
					if(ae.creator > 0) return;
					if(ae.game.equals("")) return;
					if(ae.split > 0){
						for(event e : rp.dataProvider.getList()){
							if(e.eid == ae.split){
								ae = e;
								break;
							}
						}
					}
					if(rp.auth == RaidPoints.AuthType.noauth) return;
					if(ae.over) return;
					if(msignlist.size() == 0 || (msignlist.get(0).game.equals(ae.game) && msignlist.get(0).server.equals(ae.server))){
						boolean ain = false;
						for(event e : msignlist) if(e.eid == ae.eid) {ain = true; break;} 
						if(!ain){
							msignlist.add(ae);
							if(ae.game.equals("")) msignBox.addItem(ae.starttime.getDate() + " - " + ae.note.split(":;:")[0] + " - " + ae.note.split(":;:")[1]);
							else msignBox.addItem(ae.starttime.getDate() + " - " + ae.dest + " - " + ae.note);
							msignBox.setVisible(true); signButton.setVisible(true); msignlabel.setVisible(true);
						}
					}

				}
				else{
					doit = true;
					Timer t = new Timer(){
						@Override
						public void run() {
							if(doit){
								rp.ViewPoints(idmap.get(event.getSelectedItem()));
							}
						}

					};
					t.schedule(300);
					cal.setSelectedAppointment(null);
				}
			}
		});

		cal.addOpenHandler(new OpenHandler<Appointment>(){
			@Override
			public void onOpen(OpenEvent<Appointment> event) {
				doit = false;
				if(rp.auth == RaidPoints.AuthType.noauth) return;
				if(idmap.get(event.getTarget()).over) return;
				if(idmap.get(event.getTarget()).game.equals("")) return;
				EventSignupBox esb = new EventSignupBox(rp,idmap.get(event.getTarget()));		
				esb.center(); esb.show();
			}
		});

		cal.addDateRequestHandler(new DateRequestHandler<Date>(){

			@Override
			public void onDateRequested(DateRequestEvent<Date> event) {
				MorePopup mp = new MorePopup(event.getTarget());
				mp.setPopupPosition(mymonth.cx,mymonth.cy); mp.show();
			}

		});

		dpick = new DatePicker();
		dpick.setValue(new Date());
		dpick.addValueChangeHandler(new ValueChangeHandler<Date>(){
			@Override
			public void onValueChange(ValueChangeEvent<Date> event) {
				cal.setDate(event.getValue());				
			}
		});
		
		
		tabbar.addSelectionHandler(new SelectionHandler<Integer>(){
			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				int sel = event.getSelectedItem();
				if(sel == tabbar.getTabCount() - 1){
					tabbar.selectTab(rp.currtab);
					if(rp.tablist.size() < 7){
					TabEditor te = new TabEditor(-1,rp);
					te.center(); te.show();
					}
					else{
						Window.alert("Max Tabs Reached");
					}
				}
				else{
					rp.currtab = sel;
					if(sel > rp.permtabs - 1) editTab.setVisible(true);
					else editTab.setVisible(false);
					rp.UpdateTabs();
					SelectTab();
				}
			}		
		});
		
		editTab = new Button("Edit Tab");
		editTab.setVisible(false);
		editTab.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				TabEditor te = new TabEditor(rp.currtab, rp);
				te.center(); te.show();
			}
		});

	}
	
	public void SetupTabs(){
		while(tabbar.getTabCount() > 0) tabbar.removeTab(tabbar.getTabCount()-1);
		for(String s : rp.tablist) tabbar.addTab(s.split(":<>:")[0]);
		tabbar.addTab("+");
	}
	
	public void SelectTab(){
		String[] split = rp.tablist.get(rp.currtab).split(":<>:");
		craids = split[1].equals("Y");
		cue = split[2].equals("Y");
		cgames = split[3];
		if(cgames.equals("!")) cgames = "";
		cgroups = split[4];
		if(cgroups.equals("!")) cgroups = "";
		HandleEvents();
	}

	public void SetupCal(){
		HorizontalPanel hpan = new HorizontalPanel();
		VerticalPanel hvpan = new VerticalPanel();
		VerticalPanel signpan = new VerticalPanel();
		HorizontalPanel hsignpan = new HorizontalPanel();
		HorizontalPanel tabpan = new HorizontalPanel();
		VerticalPanel dpickpan = new VerticalPanel();
		msignBox = new ListBox();
		msignBox.setVisibleItemCount(10);
		msignBox.setWidth("300px");
		signButton = new Button("Sign Up");
		msignlabel = new HTML("Double click event to remove");	

		hsignpan.setSpacing(3);
		hsignpan.add(signButton); hsignpan.add(msignlabel);
		signpan.add(msignBox); signpan.add(hsignpan);
		msignBox.setVisible(false); signButton.setVisible(false); msignlabel.setVisible(false);
		hpan.setSpacing(2);
		vpan.setSpacing(3);
		hvpan.add(legend); hvpan.add(adminin); hvpan.add(listButton);
		dpickpan.add(dpick); dpickpan.add(calheight);
		hpan.add(dpickpan); hpan.add(hvpan); hpan.add(signpan);
		//dpan.addNorth(cal,50);
		vpan.add(cal);
		//tabpan.add(tabbar); tabpan.add(editTab);
		tabbar.setWidth("90px");
		tabbar.setHeight("250px");
		tabbar.addStyleName("calendartabs");
		rp.sideTabPan.add(tabbar);
		rp.sideTabPan.add(editTab);
		//vpan.add(tabpan);
		vpan.add(hpan);
		vpan.setWidth("100%");
		ChangeHeight();
		//dpan.add(hpan);

		msignBox.addDoubleClickHandler(new DoubleClickHandler(){
			@Override
			public void onDoubleClick(DoubleClickEvent event) {
				int i = msignBox.getSelectedIndex();
				msignBox.removeItem(i);
				msignlist.remove(i);
				if(msignlist.size() == 0){
					msignBox.setVisible(false);
					signButton.setVisible(false);
					msignlabel.setVisible(false);
				}
			}
		});

		signButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				EventSignupBoxMutli es = new EventSignupBoxMutli(rp,msignlist);
				es.center(); es.show();
			}
		});

	}

	public void ChangeHeight(){
		if(rp.calheight == 0) cal.setHeight("920px"); 
		else cal.setHeight("1200px");
	}

	public void ChangeTime(){
		for(Appointment a : cal.getAppointments()){
			event evt = idmap.get(a);
			if(evt.game.equals("")) a.setTitle(evt.starttime.getTime(rp.mil) + " " + evt.note.split(":;:")[0]);
			else a.setTitle((evt.split > 0 ? "->" : "") + evt.starttime.getTime(rp.mil) + " " + evt.dest + "<br>" + evt.note);
		}
	}

	public class MyApp extends Appointment{

		boolean md;

		public MyApp(){
			super();
			md = false;
		}
		public void SetMultiDay(boolean imd){
			md = imd;
		}

		@Override
		public boolean isMultiDay(){
			return md;
		}
	}

	public void ClearMutli(){
		msignlist.clear();
		msignBox.clear();
		msignBox.setVisible(false);
		signButton.setVisible(false);
		msignlabel.setVisible(false);
	}

	@Override
	public void Redraw() {
		for(Appointment appt : cal.getAppointments()){
			event e = idmap.get(appt);
			if(e != null){
				if(e.attend.equals("slotted")){
					appt.setStyle(AppointmentStyle.GREEN);
				}
				else if(e.attend.equals("signedup") || e.attend.equals("canceled")){
					appt.setStyle(AppointmentStyle.BLUE);
				}
				else if(e.attend.equals("standby")){
					appt.setStyle(AppointmentStyle.LIGHT_PURPLE);
				}
				else{
					appt.setStyle(AppointmentStyle.GREY);
				}
			}
		}
		rp.tPanel.forceLayout();
		cal.doLayout();
	}

	@Override
	public void HandleAuthChange(AuthType atype) {
		if(prevmil != rp.mil){
			prevmil = rp.mil;
			ChangeTime();
		}
		if(rp.calheight == 0) calheight.setValue(false);
		else calheight.setValue(true);
		ChangeHeight();
		Redraw();
		switch(atype){
		case admin:
			adminin.setVisible(true);
			break;
		case cl:
			adminin.setVisible(true);
			break;
		default:
			adminin.setVisible(false);
			break;
		}	
	}

	@Override
	public void HandleEvents() {
		cal.clearAppointments();
		idmap.clear();
		cal.suspendLayout();
		for(int i = 0; i < rp.dataProvider.getList().size(); i++){
			event e = rp.dataProvider.getList().get(i);
			if(TabFilter(e)) AddEventNL(e);
		}
		cal.resumeLayout();
		rp.tPanel.forceLayout();
		cal.doLayout();
	}

	@Override
	public void AddEvent(event evt){
		if(TabFilter(evt)) AddEventNL(evt);
		rp.tPanel.forceLayout();
		cal.doLayout();
	}

	public void RemoveEvent(event evt){
		for(Appointment a : cal.getAppointments()){
			if(idmap.get(a).eid == evt.eid){
				cal.removeAppointment(a);
				break;
			}
		}
	}

	public void AddEventNL(event evt) {
		MyApp appt = new MyApp();
		appt.SetMultiDay(true);
		int si = evt.split > 0 ? 1 : 0; 
		Date startDt = new Date(evt.starttime.year,evt.starttime.month-1,evt.starttime.day,evt.starttime.hour,evt.starttime.minute + si);
		Date endDt = new Date(evt.endtime.year,evt.endtime.month-1,evt.endtime.day,evt.endtime.hour,evt.endtime.minute);
		appt.setStart(startDt);
		appt.setEnd(endDt);
		appt.setDescription(evt.note);
		if(evt.game.equals("")){
			appt.setTitle("<font color=\"FDD017\">[G]</font> " + evt.starttime.getTime(rp.mil) + " <font color=\"FDD017\">" + evt.note.split(":;:")[0] + "</font><br>" + evt.note.split(":;:")[1]);
			appt.setDescription(evt.note.split(":;:")[1]);
		}
		else if(evt.creator == 0){
			appt.setTitle((evt.split > 0 ? "->" : "") + evt.starttime.getTime(rp.mil) + " " + evt.dest + "<br><font color=\"FFFF00\">" + evt.group + "</font><br>" + evt.note);
		}
		else{
			appt.setTitle(evt.starttime.getTime(rp.mil) + " <font color=\"FF0000\">" + evt.game + "</font><br>" + (evt.dest.equals("") ? "" : "<font color=\"ADD8E6\">" + evt.dest + "</font><br>") + evt.note);
		}
		//	appt.setTitle("test");
		if(evt.attend.equals("slotted")){
			appt.setStyle(AppointmentStyle.GREEN);
		}
		else if(evt.attend.equals("signedup") || evt.attend.equals("canceled")){
			appt.setStyle(AppointmentStyle.BLUE);
		}
		else if(evt.attend.equals("standby")){
			appt.setStyle(AppointmentStyle.LIGHT_PURPLE);
		}
		else{
			appt.setStyle(AppointmentStyle.GREY);
		}
		idmap.put(appt, evt);
		cal.addAppointment(appt);		
	}

	@Override
	public event GetEvent(int eid) {
		for(Appointment a : idmap.keySet()){
			event e = idmap.get(a);
			if(e.eid == eid){
				return e;
			}
		}
		return null;
	}
	
	public boolean TabFilter(event evt){
		if(evt.game.equals("")) return true;
		boolean intab = true;
		if(!craids && evt.creator == 0) intab = false;
		if(!cue && evt.creator > 0) intab = false;
		if(!cgames.equals("") && !cgames.contains(evt.game)) intab = false;
		if(evt.creator == 0 && !cgroups.equals("") && !cgroups.contains(evt.group)) intab = false;
		return intab;
	}
	
	public class MSignupPopup extends PopupPanel{
		HTML slabel;
		
		MSignupPopup(){
			super(true);
			slabel = new HTML();
			setWidget(slabel);
			Redraw();
		}
		
		public void Redraw(){
			StringBuilder sb = new StringBuilder();
			for(int i = 0; i < msignBox.getItemCount(); i++){
				sb.append((i > 0 ? "<br>" : "") + msignBox.getItemText(i));
			}
			slabel.setHTML(sb.toString());
		}
	}

	public class MorePopup extends PopupPanel{
		NCDate date;
		VerticalPanel vpan;
		HashMap<HTML,event> cmap;
		MorePopup(Date mdate){
			super(true);
			cmap = new HashMap<HTML,event>();
			date = new NCDate(mdate);
			vpan = new VerticalPanel();
			vpan.setSpacing(3);
			setWidget(vpan);
			for(event e : rp.dataProvider.getList()){
				if(e.starttime.sameDay(date) && TabFilter(e)){
					final HTML eh = new HTML();
					cmap.put(eh,e);
					String color = "#8997A5";
					if(e.attend.equals("signedup")) color = "#668CD9";
					else if(e.attend.equals("standby")) color = "#A992A9";
					else if(e.attend.equals("canceled")) color = "red";
					else if(e.attend.equals("slotted")) color = "#4CB052";		
					if(e.game.equals("")) eh.setHTML("<table bgcolor=\"" + color + "\"><tr><td>" + "<font color=\"FDD017\">[G]</font> " + "<font color=\"white\">" + e.starttime.getTime(rp.mil) + " <font color=\"FDD017\">" + e.note.split(":;:")[0] + "</font> - " + e.note.split(":;:")[1] + "</font></td></tr></table>");
					else eh.setHTML("<table bgcolor=\"" + color + "\"><tr><td>" + "<font color=\"white\">" + (e.split > 0 ? "->" : "") + e.starttime.getTime(rp.mil) + " " + e.dest + " - " + e.note + "</font></td></tr></table>");

					eh.addClickHandler(new ClickHandler(){
						@Override
						public void onClick(ClickEvent event) {
							if(rp.ctrldown){
								event ae = cmap.get(eh);
								if(ae.split > 0){
									for(event ee : rp.dataProvider.getList()){
										if(ee.eid == ae.split){
											ae = ee;
											break;
										}
									}
								}
								if(rp.auth == RaidPoints.AuthType.noauth) return;
								if(ae.over) return;
								if(msignlist.size() == 0 || (msignlist.get(0).game.equals(ae.game) && msignlist.get(0).server.equals(ae.server))){
									boolean ain = false;
									for(event e : msignlist) if(e.eid == ae.eid) {ain = true; break;} 
									if(!ain){
										msignlist.add(ae);
										msignBox.addItem(ae.starttime.getDate() + " - " + ae.dest + " - " + ae.note);
										msignBox.setVisible(true); signButton.setVisible(true); msignlabel.setVisible(true);
									}
								}
							}
							else{
								rp.ViewPoints(cmap.get(eh));
								cmap = null;
								hide();
							}
						}
					});

					//					eh.addDoubleClickHandler(new DoubleClickHandler(){
					//
					//						@Override
					//						public void onDoubleClick(DoubleClickEvent event) {
					//							if(rp.auth == RaidPoints.AuthType.noauth) return;
					//							if(cmap.get(eh).over) return;
					//							EventSignupBox esb = new EventSignupBox(rp,cmap.get(eh));		
					//							esb.center(); esb.show();		
					//							cmap = null;
					//							hide();
					//						}
					//						
					//					});

					vpan.add(eh);
				}
			}
		}

	}
}
